﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Reflection;
using System.Xml.Schema;
using System.Xml;

namespace ServerSide.Model
{
    public class WordList
    {
        [XmlElement("Subject")]
        public List<Subject> Subjects { get; set; }

        /// <summary>
        /// Singleton pattern to guarantee only one instance of this class will be created
        /// </summary>
        public static WordList instance;

        /// <summary>
        /// The object for synchronization
        /// </summary>
        private static readonly object synLock = new object();

        /// <summary>
        /// Schema for XML WordListSchema validation
        /// </summary>
        private static XmlSchema WordListSchema;

        /// <summary>
        /// XML data file
        /// </summary>
        private const string xmlData = "data.xml";

        /// <summary>
        /// Full name of xsd file data
        /// </summary>
        private const string xsdData = "data.xsd";

        /// <summary>
        /// The property of instance
        /// </summary>
        public static WordList GetInstance()
        {
            lock (synLock)
            {
                if (instance == null)
                {
                    var cfgFile = Path.Combine(GetAppPath(), "Data", xmlData);

                    // Create schemas
                    WordListSchema = XmlValidator.Instance.CreateSchema(xsdData);

                    // Validate xml content using schema setting
                    XmlValidator.Instance.ValidateXML(cfgFile, WordListSchema);

                    // Start to deserialize
                    using (XmlTextReader xreader = new XmlTextReader(cfgFile))
                    {
                        xreader.Namespaces = false;
                        try
                        {
                            var x = new XmlSerializer(typeof(WordList));
                            instance = x.Deserialize(xreader) as WordList;
                        }
                        catch (Exception ex)
                        {
                            throw new Exception(string.Format("Cannot deserialize WordList, WordList => {0}", ex.Message));
                        }
                    }
                }
                return instance;
            }        
        }

        /// <summary>
        /// Get random subject
        /// </summary>
        /// <returns></returns>
        public Subject GetRandom(List<Subject> subjects)
        {
            Random rand = new Random((int)DateTime.Now.Ticks);
            int numIterations = rand.Next(0, subjects.Count);
            return subjects[numIterations];
        }

        /// <summary>
        /// Get application path
        /// </summary>
        /// <returns></returns>
        private static string GetAppPath()
        {
            return Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName;
        }
    }

    public class Subject
    {
        [XmlAttribute("Name")]
        public string Name { get; set; }

        [XmlElement("Word")]
        public List<Word> Words { get; set; }

        /// <summary>
        /// Get random Word
        /// </summary>
        /// <returns></returns>
        public Word GetRandom(List<Word> words)
        {
            Random rand = new Random((int)DateTime.Now.Ticks);
            int numIterations = rand.Next(0, words.Count);
            return words[numIterations];
        }
    }

    public class Word
    {
        [XmlElement("Suggestion")]
        public string Suggestion { get; set; }

        [XmlElement("Answer")]
        public string Answer { get; set; }
    }
}
